﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Xml;
using System.Xml.Serialization;
using Electronic_Catalog_XML_Generator_Libs.models;
using Electronic_Catalog_XML_Generator_Libs.tools;
using Microsoft.WindowsAPICodePack.Dialogs;
using Prism.Commands;
using Prism.Mvvm;
using Ini.Net;
using Ini;
using System.Drawing;
using System.Windows.Media;
using ICSharpCode.SharpZipLib.Zip;
using System.IO.Compression;
using ZipFile = ICSharpCode.SharpZipLib.Zip.ZipFile;
using Crews.Utility.TgaSharp;
using System.Drawing.Imaging;
using Color = System.Drawing.Color;
using System.Diagnostics;
using Electronic_Catalog_XML_Generator.Models;
using System.Security.AccessControl;

namespace Electronic_Catalog_XML_Generator.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        string IniCfg = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Configuration.ini";
        IniFile ini = null;
        public MainWindowViewModel()
        {
            DirectoryInfo dirinfo = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
            dirinfo.SetAccessControl(new DirectorySecurity());
            if (!File.Exists(IniCfg))
                File.Create(IniCfg);
            ini = new IniFile(IniCfg);
            bnOpenDir = new DelegateCommand(OpenDir);
            bnOutPutDir = new DelegateCommand(OutPutDir);
            bnSelected = new DelegateCommand<SelectionChangedEventArgs>(DataGridSelected);
            bnPicTrans = new DelegateCommand(PicTrans);
            bnSelectPNG = new DelegateCommand(SelectPNG);
            bnOpenPNG = new DelegateCommand(OpenPNG);
            Files = new ObservableCollection<FileModel>();
            ZipFileList = new ObservableCollection<ZipFileModel>();
            WaitToChanged = new ObservableCollection<FileModel>();
            FromSelectedBrush = new SolidColorBrush();
            ToSelectedBrush = new SolidColorBrush();
            Task.Run(() =>
            {
                var path = ini.ReadString("AppConfig", "DirPath");

                if (Directory.Exists(path))
                {
                    DirPath = path;
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        PNGPath = ini.ReadString("AppConfig", "PNGPath");
                        loadfile();
                    });
                }
            });
            CanUse = true;
        }
        #region properies

        private ObservableCollection<ZipFileModel> _zipFileList;

        public ObservableCollection<ZipFileModel> ZipFileList
        {
            get { return _zipFileList; }
            set { SetProperty(ref _zipFileList, value); }
        }



        private int _totalfileCount;

        public int TotalFileCount
        {
            get { return _totalfileCount; }
            set { SetProperty(ref _totalfileCount, value); }
        }

        private int _chooseFileCount;

        public int ChooseFileCount
        {
            get { return _chooseFileCount; }
            set { SetProperty(ref _chooseFileCount, value); }
        }

        private double _blurEffect;

        public double BlurEffect
        {
            get { return _blurEffect; }
            set { SetProperty(ref _blurEffect, value); }
        }

        private bool _isBusy;

        public bool IsBusy
        {
            get { return _isBusy; }
            set { SetProperty(ref _isBusy, value); }
        }

        private string _messageinfo;

        public string MessageInfo
        {
            get { return _messageinfo; }
            set { SetProperty(ref _messageinfo, value); }
        }

        private bool _canUse = true;

        public bool CanUse
        {
            get { return _canUse; }
            set { SetProperty(ref _canUse, value); }
        }


        private SolidColorBrush _toSelectedBrush;

        public SolidColorBrush ToSelectedBrush
        {
            get { return _toSelectedBrush; }
            set { SetProperty(ref _toSelectedBrush, value); }
        }

        private SolidColorBrush _fromSelectedBrush;

        public SolidColorBrush FromSelectedBrush
        {
            get { return _fromSelectedBrush; }
            set { SetProperty(ref _fromSelectedBrush, value); }
        }

        private double _lightLevel;

        public double LightLevel
        {
            get { return _lightLevel; }
            set { SetProperty(ref _lightLevel, value); }
        }


        private object? _propertyGrid;

        public object? PropertyGrid
        {
            get { return _propertyGrid; }
            set { SetProperty(ref _propertyGrid, value); }
        }

        private bool _isSavePNG;

        public bool IsSavePNG
        {
            get { return _isSavePNG; }
            set { SetProperty(ref _isSavePNG, value); }
        }

        private string _dirPath;
        /// <summary>
        /// 文档目录
        /// </summary>
        public string DirPath
        {
            get { return _dirPath; }
            set { SetProperty(ref _dirPath, value); }
        }
        private string _pngPath;

        public string PNGPath
        {
            get { return _pngPath; }
            set { SetProperty(ref _pngPath, value); }
        }
        public ObservableCollection<FileModel> Files { get; set; }
        public ObservableCollection<FileModel> WaitToChanged { get; set; }
        #endregion
        #region func
        public void OpenPNG()
        {
            if (Directory.Exists(PNGPath))
            {
                Process.Start("explorer.exe", PNGPath);
            }
        }
        public void PicTrans()
        {
            UnEnable();
            MessageInfo = "处理中，请稍后";
            Task.Run(async () =>
            {
                if (Files == null)
                    Application.Current.Dispatcher.Invoke(() => Enable());
                if (Files.Count <= 0)
                    Application.Current.Dispatcher.Invoke(() => Enable());
                try
                {
                    foreach (var item in Files)
                    {
                        if (File.Exists(item.FileFullPath))
                        {
                            ZipFile zip = new ZipFile(item.FileFullPath);
                            for (int i = 0; i < zip.Count; i++)
                            {
                                var name = zip[i].Name;
                                if (name.EndsWith(".tga"))
                                {
                                    if (name.EndsWith("preview.tga"))
                                    {
                                        ZipEntry? entry1 = zip.GetEntry(name);
                                        if (entry1 != null)
                                        {
                                            using (Stream mem = zip.GetInputStream(entry1))
                                            {
                                                using (MemoryStream mmm = new MemoryStream())
                                                {
                                                    mem.CopyTo(mmm);
                                                    TGA t = new TGA(mmm);
                                                    if (IsSavePNG)
                                                    {
                                                        if (Directory.Exists(PNGPath))
                                                        {
                                                            var p1 = Path.Combine(PNGPath, "icon_preview", "png");
                                                            if (!Directory.Exists(p1))
                                                                Directory.CreateDirectory(p1);
                                                            t.ToBitmap().Save(Path.Combine(p1, Path.GetFileNameWithoutExtension(item.FileFullPath) + "_Preview.png"), ImageFormat.Png);
                                                        }
                                                    }
                                                    Application.Current.Dispatcher.Invoke(() =>
                                                    {
                                                        var map = t.ToBitmap();
                                                        map.MakeTransparent();
                                                        if (Directory.Exists(PNGPath))
                                                        {
                                                            var p1 = Path.Combine(PNGPath, "icon_preview", "transparent");
                                                            if (!Directory.Exists(p1))
                                                                Directory.CreateDirectory(p1);
                                                            map.Save(Path.Combine(p1, Path.GetFileNameWithoutExtension(item.FileFullPath) + "_Preview.png"), ImageFormat.Png);
                                                        }
                                                    });
                                                }
                                            }
                                        }
                                    }
                                    else if (name.EndsWith("icon.tga"))
                                    {
                                        #region obs
                                        ZipEntry? entry2 = zip.GetEntry(name);
                                        if (entry2 != null)
                                        {
                                            using (Stream mem = zip.GetInputStream(entry2))
                                            {
                                                using (MemoryStream mmm = new MemoryStream())
                                                {
                                                    mem.CopyTo(mmm);
                                                    TGA t = new TGA(mmm);
                                                    if (IsSavePNG)
                                                    {
                                                        if (Directory.Exists(PNGPath))
                                                        {
                                                            var p1 = Path.Combine(PNGPath, "layout_icon", "png");
                                                            //提取出来的PNG
                                                            if (!Directory.Exists(p1))
                                                            {
                                                                Directory.CreateDirectory(p1);
                                                            }
                                                            t.ToBitmap().Save(Path.Combine(p1, Path.GetFileNameWithoutExtension(item.FileFullPath) + "_Icon.png"), ImageFormat.Png);
                                                        }
                                                    }
                                                    Application.Current.Dispatcher.Invoke(() =>
                                                    {
                                                        var map = t.ToBitmap();
                                                        map.MakeTransparent();
                                                        if (Directory.Exists(PNGPath))
                                                        {
                                                            var p1 = Path.Combine(PNGPath, "layout_icon", "transparent");
                                                            if (!Directory.Exists(p1))
                                                            {
                                                                Directory.CreateDirectory(p1);
                                                            }
                                                            map.Save(Path.Combine(p1, Path.GetFileNameWithoutExtension(item.FileFullPath) + "_Icon.png"), ImageFormat.Png);;
                                                        }
                                                    });
                                                }
                                            }
                                        }
                                        #endregion
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    Application.Current.Dispatcher.Invoke(() => Enable());
                }
                await Task.Delay(new Random().Next(500, 3000));
                Application.Current.Dispatcher.Invoke(() => Enable());
            });
        }
        public void SelectPNG()
        {
            CommonOpenFileDialog dialog = new CommonOpenFileDialog();
            dialog.DefaultDirectory = Environment.SpecialFolder.MyDocuments.ToString();
            dialog.IsFolderPicker = true;
            dialog.Title = "请选择文件目录";
            dialog.Multiselect = false;
            if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
            {
                PNGPath = dialog.FileName;
                ini.WriteString("AppConfig", "PNGPath", dialog.FileName);
            }
        }

        private void UnEnable()
        {
            IsBusy = true;
            BlurEffect = 25;
            CanUse = false;
        }
        private void Enable()
        {
            IsBusy = false;
            BlurEffect = 0;
            CanUse = true;
        }
        public void DataGridSelected(SelectionChangedEventArgs args)
        {
            if (args.AddedItems.Count > 0)
            {
                PropertyGrid = args.AddedItems[0];
                foreach (var item in args.AddedItems)
                {
                    WaitToChanged.Add(item as FileModel);
                }
            }
            if (args.RemovedItems.Count > 0)
            {
                foreach (var item in args.RemovedItems)
                {
                    WaitToChanged.Remove(item as FileModel);
                }
            }
            ChooseFileCount = WaitToChanged == null ? 0 : WaitToChanged.Count;

            Task.Run(() =>
            {
                if (args.AddedItems.Count > 0)
                {
                    Application.Current.Dispatcher.Invoke(() => { ZipFileList.Clear(); });
                    var fullpath = (args.AddedItems[0] as FileModel).FileFullPath;
                    if (fullpath != null)
                    {
                        using (ZipFile zip = new ZipFile(fullpath))
                        {
                            for (int i = 0; i < zip.Count; i++)
                            {
                                Application.Current.Dispatcher.Invoke(() =>
                                {
                                    ZipFileList.Add(new ZipFileModel() { FileName = zip[i].Name, FileVersion = zip[i].Size, FileDataTime = zip[i].DateTime.ToString() });
                                });
                            }
                        }
                    }
                }
            });
        }
        //数据修改通知
        public void notify(string str, string value)
        {
            switch (str)
            {
                case "Manufacturer":
                    for (int i = 0; i < WaitToChanged.Count; i++)
                    {
                        WaitToChanged[i].CanNotify = false;
                        WaitToChanged[i].Manufacturer = value;
                        WaitToChanged[i].CanNotify = true;
                    }
                    ini.WriteString("AppConfig", "Manufacturer", value);
                    break;
                case "Type":
                    for (int i = 0; i < WaitToChanged.Count; i++)
                    {
                        WaitToChanged[i].CanNotify = false;
                        WaitToChanged[i].Type = value;
                        WaitToChanged[i].CanNotify = true;
                    }
                    ini.WriteString("AppConfig", "Type", value);
                    break;
                case "File":
                    for (int i = 0; i < WaitToChanged.Count; i++)
                    {
                        WaitToChanged[i].CanNotify = false;
                        WaitToChanged[i].File = value;
                        WaitToChanged[i].CanNotify = true;
                    }
                    ini.WriteString("AppConfig", "File", value);
                    break;
                case "Description":
                    for (int i = 0; i < WaitToChanged.Count; i++)
                    {
                        WaitToChanged[i].CanNotify = false;
                        WaitToChanged[i].Description = value;
                        WaitToChanged[i].CanNotify = true;
                    }
                    ini.WriteString("AppConfig", "Description", value);
                    break;
                case "MaxPayLoad":
                    for (int i = 0; i < WaitToChanged.Count; i++)
                    {
                        WaitToChanged[i].CanNotify = false;
                        WaitToChanged[i].MaxPayLoad = value;
                        WaitToChanged[i].CanNotify = true;
                    }
                    break;
                case "Author":
                    for (int i = 0; i < WaitToChanged.Count; i++)
                    {
                        WaitToChanged[i].CanNotify = false;
                        WaitToChanged[i].Author = value;
                        WaitToChanged[i].CanNotify = true;
                    }
                    ini.WriteString("AppConfig", "Author", value);
                    break;
                case "Email":
                    for (int i = 0; i < WaitToChanged.Count; i++)
                    {
                        WaitToChanged[i].CanNotify = false;
                        WaitToChanged[i].Email = value;
                        WaitToChanged[i].CanNotify = true;
                    }
                    ini.WriteString("AppConfig", "Email", value);
                    break;
                case "Website":
                    for (int i = 0; i < WaitToChanged.Count; i++)
                    {
                        WaitToChanged[i].CanNotify = false;
                        WaitToChanged[i].Website = value;
                        WaitToChanged[i].CanNotify = true;
                    }
                    ini.WriteString("AppConfig", "Website", value);
                    break;
                case "VcId":
                    for (int i = 0; i < WaitToChanged.Count; i++)
                    {
                        WaitToChanged[i].CanNotify = false;
                        WaitToChanged[i].VcId = value;
                        WaitToChanged[i].CanNotify = true;
                    }
                    break;
                case "ModelType":
                    for (int i = 0; i < WaitToChanged.Count; i++)
                    {
                        WaitToChanged[i].CanNotify = false;
                        WaitToChanged[i].ModelType = value;
                        WaitToChanged[i].CanNotify = true;
                    }
                    break;
                case "Tags":
                    for (int i = 0; i < WaitToChanged.Count; i++)
                    {
                        WaitToChanged[i].CanNotify = false;
                        WaitToChanged[i].Tags = value;
                        WaitToChanged[i].CanNotify = true;
                    }
                    ini.WriteString("AppConfig", "Tags", value);
                    break;
                case "IconAddr":
                    for (int i = 0; i < WaitToChanged.Count; i++)
                    {
                        WaitToChanged[i].CanNotify = false;
                        WaitToChanged[i].IconAddr = value;
                        WaitToChanged[i].CanNotify = true;
                    }
                    break;
                case "PreviewAddr":
                    for (int i = 0; i < WaitToChanged.Count; i++)
                    {
                        WaitToChanged[i].CanNotify = false;
                        WaitToChanged[i].PreviewAddr = value;
                        WaitToChanged[i].CanNotify = true;
                    }
                    break;
                default:
                    break;
            }
        }
        //点击打开按钮
        public void OpenDir()
        {
            CommonOpenFileDialog dialog = new CommonOpenFileDialog();
            dialog.DefaultDirectory = Environment.SpecialFolder.MyDocuments.ToString();
            dialog.IsFolderPicker = true;
            dialog.Title = "请选择文件目录";
            dialog.Multiselect = false;
            if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
            {
                ini.WriteString("AppConfig", "DirPath", dialog.FileName);
                Files.Clear();
                DirPath = dialog.FileName;
                loadfile();
                ini.WriteString("AppConfig", "DirPath", dialog.FileName);
            }
        }
        public void loadfile()
        {
            try
            {
                Application.Current.Dispatcher.Invoke(() => { UnEnable(); });
                var result = new FileTools(DirPath, "*.vcmx");
                result.Notifys = notify;
                result.LoadFiles();
                if (result.Files != null)
                {
                    var r1 = ini.ReadString("AppConfig", "Type");
                    var r2 = ini.ReadString("AppConfig", "Manufacturer");
                    var r3 = ini.ReadString("AppConfig", "File");
                    var r5 = ini.ReadString("AppConfig", "Author");
                    var r6 = ini.ReadString("AppConfig", "Website");
                    var r7 = ini.ReadString("AppConfig", "Email");
                    var r10 = ini.ReadString("AppConfig", "Description");
                    var r12 = ini.ReadString("AppConfig", "Tags");
                    foreach (var item in result.Files.Values)
                    {
                        item.CanNotify = true;
                        item.File = r3;
                        item.Type = r1;
                        item.Author = r5;
                        item.Website = r6;
                        item.Email = r7;
                        item.Description = r10;
                        item.Tags = r12;
                        Files.Add(item);
                    }
                    foreach (var item in Files)
                    {
                        ZipFile zipfile = new ZipFile(item.FileFullPath);
                        var model = zipfile.GetEntry("model.xml");
                        using (StreamReader reader = new StreamReader(zipfile.GetInputStream(model)))
                        {
                            XmlDocument doc = new XmlDocument();
                            doc.Load(reader);
                            var nodelsit = doc.GetElementsByTagName("VcModel");
                            XmlNode? iss = nodelsit[0]?.ChildNodes[0];
                            if (iss != null)
                            {
                                foreach (XmlNode ix1 in iss.ChildNodes)
                                {
                                    if (ix1.Attributes != null && ix1.Attributes.Count > 0)
                                    {
                                        switch (ix1.Attributes[0].Value)
                                        {
                                            case "Name":
                                                item.Name = ix1.InnerText;
                                                break;
                                            case "VCID":
                                                item.VcId = ix1.InnerText;
                                                break;
                                            case "ModelType":
                                                item.ModelType = ix1.InnerText;

                                                break;
                                            case "Manufacturer":
                                                item.Manufacturer = ix1.InnerText;
                                                break;
                                            case "MaxPayload":
                                                item.MaxPayLoad = ix1.InnerText;
                                                break;
                                            case "Author":
                                                item.Author = ix1.InnerText;
                                                break;
                                            case "Website":
                                                item.Website = ix1.InnerText;
                                                break;
                                            case "Revision":
                                                item.Revision = ix1.InnerText;
                                                break;
                                            case "DetailedRevision":
                                                item.DetailedRevision = ix1.InnerText;
                                                break;
                                            case "Reach":
                                                item.Reach = ix1.InnerText;
                                                break;
                                            case "IsDeprecated":
                                                item.IsDeprecated = ix1.InnerText;
                                                break;
                                            case "Tags":
                                                item.Tags = ix1.InnerText;
                                                break;
                                            case "Email":
                                                item.Email = ix1.InnerText;
                                                break;
                                            case "DateModified":
                                                item.DateModified = ix1.InnerText;
                                                break;
                                            default:
                                                break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                Application.Current.Dispatcher.Invoke(() => Enable());
            }
            finally
            {
                TotalFileCount = Files == null ? 0 : Files.Count;
                Application.Current.Dispatcher.Invoke(() => Enable());
            }
        }
        //点击输出按钮
        public void OutPutDir()
        {
            XmlDocument doc = new XmlDocument();
            XmlDeclaration xmldec = doc.CreateXmlDeclaration("1.0", "utf-8", null);
            doc.InsertBefore(xmldec, doc.DocumentElement);
            var root = doc.CreateElement("Components");
            root.SetAttribute("Count", Files.Count.ToString());
            root.SetAttribute("Version", "3.6");
            foreach (var item in Files)
            {
                var child = doc.CreateElement("VcmComponent");
                #region nodes

                var cn1 = doc.CreateElement(nameof(item.Name));
                cn1.InnerText = item.Name;

                var cn2 = doc.CreateElement(nameof(item.Description));
                cn2.InnerText = item.Description;

                var cn3 = doc.CreateElement(nameof(item.Type));
                cn3.InnerText = item.Type;

                var cn4 = doc.CreateElement(nameof(item.Manufacturer));
                cn4.InnerText = item.Manufacturer;

                var cn5 = doc.CreateElement(nameof(item.MaxPayLoad));
                cn5.InnerText = item.MaxPayLoad;

                var cn6 = doc.CreateElement(nameof(item.Reach));
                cn6.InnerText = item.Reach;

                var cn7 = doc.CreateElement(nameof(item.Author));
                cn7.InnerText = item.Author;

                var cn8 = doc.CreateElement(nameof(item.Email));
                cn8.InnerText = item.Email;

                var cn9 = doc.CreateElement(nameof(item.Website));
                cn9.InnerText = item.Website;

                var cn10 = doc.CreateElement(nameof(item.DetailedRevision));
                cn10.InnerText = item.DetailedRevision;

                var cn11 = doc.CreateElement(nameof(item.Revision));
                cn11.InnerText = item.Revision;

                var cn12 = doc.CreateElement(nameof(item.VcId));
                cn12.InnerText = item.VcId;

                var cn13 = doc.CreateElement(nameof(item.IsDeprecated));
                cn13.InnerText = item.IsDeprecated;

                var cn14 = doc.CreateElement(nameof(item.Tags));
                cn14.InnerText = item.Tags;

                var cn15 = doc.CreateElement(nameof(item.File));
                cn15.InnerText = item.File + item.NameAndExc;

                var cn16 = doc.CreateElement(nameof(item.Icon));
                cn16.InnerText = item.IconAddr + item.Icon;

                var cn17 = doc.CreateElement(nameof(item.PreviewIcon));
                cn17.InnerText = item.PreviewAddr + item.PreviewIcon;

                var cn18 = doc.CreateElement(nameof(item.DateModified));
                cn18.InnerText = item.DateModified;


                var cn19 = doc.CreateElement(nameof(item.FileSize));
                cn19.InnerText = item.FileSize;

                var cn20 = doc.CreateElement(nameof(item.ModelType));
                cn20.InnerText = item.ModelType;
                #endregion
                #region addnodes
                child.AppendChild(cn1);
                child.AppendChild(cn2);
                child.AppendChild(cn3);
                child.AppendChild(cn4);
                child.AppendChild(cn5);
                child.AppendChild(cn6);
                child.AppendChild(cn7);
                child.AppendChild(cn8);
                child.AppendChild(cn9);
                child.AppendChild(cn10);
                child.AppendChild(cn11);
                child.AppendChild(cn12);
                child.AppendChild(cn13);
                child.AppendChild(cn14);
                child.AppendChild(cn15);
                child.AppendChild(cn16);
                child.AppendChild(cn17);
                child.AppendChild(cn18);
                child.AppendChild(cn19);
                child.AppendChild(cn20);
                root.AppendChild(child);
                #endregion
            }
            doc.AppendChild(root);
            CommonSaveFileDialog dialog = new CommonSaveFileDialog();
            dialog.Filters.Add(new CommonFileDialogFilter("XML文件(*.xml)", "*.xml"));
            dialog.DefaultDirectory = Environment.SpecialFolder.DesktopDirectory.ToString();
            dialog.Title = "请选择文件保存的位置";

            dialog.DefaultFileName = DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss");
            if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
                doc.Save(dialog.FileName);
        }
        #endregion
        #region cmd
        public DelegateCommand bnOpenDir { get; set; }
        public DelegateCommand bnOutPutDir { get; set; }
        public DelegateCommand bnPicTrans { get; set; }
        public DelegateCommand bnSelectPNG { get; set; }
        public DelegateCommand bnOpenPNG { get; set; }
        public DelegateCommand<SelectionChangedEventArgs> bnSelected { get; set; }
        #endregion
    }
}
